package com.fqgame.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fqgame.auth.dto.LoginRequest;
import com.fqgame.auth.dto.LoginResponse;
import com.fqgame.auth.entity.User;
import com.fqgame.auth.mapper.UserMapper;
import com.fqgame.auth.service.UserService;
import com.fqgame.common.exception.BusinessException;
import com.fqgame.common.response.ResultCode;
import com.fqgame.common.utils.JwtUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 用户服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final PasswordEncoder passwordEncoder;
    private final JwtUtil jwtUtil;
    private final RedisTemplate<String, Object> redisTemplate;

    private static final String TOKEN_PREFIX = "token:";
    private static final long TOKEN_EXPIRE = 24; // 24小时

    @Override
    public LoginResponse login(LoginRequest loginRequest) {
        // 根据用户名查询用户
        User user = getByUsername(loginRequest.getUsername());
        if (user == null) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "用户名或密码错误");
        }

        // 校验密码
        if (!passwordEncoder.matches(loginRequest.getPassword(), user.getPassword())) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "用户名或密码错误");
        }

        // 校验用户状态
        if (user.getStatus() == 0) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED.getCode(), "账号已被禁用");
        }

        // 查询用户角色
        List<String> roles = baseMapper.selectRoleCodesByUserId(user.getId());

        // 生成token
        String token = jwtUtil.generateToken(user.getUsername());

        // 将token存入Redis
        redisTemplate.opsForValue().set(TOKEN_PREFIX + token, user.getUsername(), TOKEN_EXPIRE, TimeUnit.HOURS);

        // 构建登录响应
        return LoginResponse.builder()
                .token(token)
                .userId(user.getId())
                .username(user.getUsername())
                .nickname(user.getNickname())
                .roles(roles)
                .build();
    }

    @Override
    public User getByUsername(String username) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, username);
        return getOne(wrapper);
    }

    @Override
    public String refreshToken(String token) {
        // 验证token是否存在于Redis
        String key = TOKEN_PREFIX + token;
        Object username = redisTemplate.opsForValue().get(key);
        if (username == null) {
            throw new BusinessException(ResultCode.UNAUTHORIZED);
        }

        // 刷新token
        String newToken = jwtUtil.refreshToken(token);
        if (newToken == null) {
            throw new BusinessException(ResultCode.UNAUTHORIZED);
        }

        // 更新Redis中的token
        redisTemplate.delete(key);
        redisTemplate.opsForValue().set(TOKEN_PREFIX + newToken, username, TOKEN_EXPIRE, TimeUnit.HOURS);

        return newToken;
    }
}